#include "MySocket.h"

#include "socketinclude.h"

#include <iostream>
#include <assert.h>


#if defined(WIN32)
#pragma comment(lib, "ws2_32.lib")
#endif

MySocket::MySocket()
    :_socket_fd(INVALID_SOCKET)
{
#if defined(_WIN32)
    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested = MAKEWORD(2, 0);

    if (WSAStartup(wVersionRequested, &wsaData) != 0)
    {
        assert(false);
    }

#endif
}
MySocket::~MySocket()
{
#if defined(_WIN32)
    WSACleanup();
#endif
}


int  MySocket::Initialization(int port)
{
    // create socket

    _socket_fd = socket(AF_INET, SOCK_STREAM,0);

    if(_socket_fd < 0)
    {
        std::cout << "socket create error " << strerror(errno) << std::endl;
        assert(false);
        return -1;
    }

    //2. bind

    struct sockaddr_in myaddr;
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(port);
    myaddr.sin_addr.s_addr = INADDR_ANY;


    if(bind(_socket_fd, (struct sockaddr*) &myaddr, sizeof(struct sockaddr)) < 0)
    {
        std::cout << "bind error " << strerror(errno) << std::endl;
        assert(false);
        return -1;
    }


    //listen

    if(listen(_socket_fd, 10) < 0)
    {
        std::cout << "listen error " << strerror(errno) <<std::endl;
        assert(false);
        return -1;
    }

    return  0;
}
int MySocket::Accept()
{
    struct sockaddr  client_addr;
    memset(&client_addr, 0, sizeof(struct sockaddr));
    int client_addr_len = sizeof(client_addr);

    int connfd = 0;

    connfd= accept(_socket_fd, (struct sockaddr*)&client_addr, &client_addr_len);

     if(connfd < 0)
     {
         switch(errno)
         {
             // 非致命错误，忽略
             case EAGAIN:
             case ECONNABORTED:
             case EINTR:
             case EMFILE:
                 break;
             // 致命错误，退出程序
             case EFAULT:
             case EINVAL:
             case ENFILE:
             case ENOMEM:
                 std::cout << "Socket::accept error: " << strerror(errno) << std::endl;
                 exit(1);
                 break;
             // 未知错误，退出程序
             default:
                 std::cout << "Socket::accept error: " << strerror(errno) << std::endl;
                 exit(1);
                 break;
         }
     }
     return connfd;

}
int  MySocket::Release()
{
    if(_socket_fd > 0)
    {
#if defined(WIN32)
        closesocket(_socket_fd);
#else
        close(_socket_fd);
#endif
        _socket_fd = INVALID_SOCKET;
    }

    return 0;
}
